#include <Ice/BuiltinSequences.ice>
#include <Glacier2/Session.ice>

/**
	El modulo Yafridng contiene la definicion de todas las estructuras,
	las excepciones y las interfaces utilizadas por Yafrid-NG.
**/

module Yafridng{

	/**
		La estructura Piece contiene los datos necesarios para especificar
		un fragmento de archivo.
	**/
	struct Piece
   {
		/**
			El campo offset contiene la posicion inicial dentro del archivo.
		**/
		int offset;
		/**
			El campo pieceSize contiene el tamaño del fragmento de archivo.
		**/
		int pieceSize;
	};

	/**
		La estructura TZone contiene los datos necesarios para especificar
		una unidad de trabajo.
	**/
   struct TZone 
   {
		/**
			El campo id contiene el identificador de una zona.
		**/
		int id;
		/**
			El campo x1 contiene la coordenada x de la esquina
			superior izquierda de la unidad de trabajo.
		**/
		int x1;
		/**
			El campo y1 contiene la coordenada y de la esquina
			superior izquierda de la unidad de trabajo.
		**/
		int y1;
		/**
			El campo x2 contiene la coordenada x de la esquina
			inferior derecha de la unidad de trabajo.
		**/
		int x2;
		/**
			El campo y2 contiene la coordenada y de la esquina
			inferior derecha de la unidad de trabajo.
		**/
		int y2;
		/**
			El campo frame contiene el numero de frame que se
			corresponde con la unidad de trabajo.
		**/
		int frame;
   };

	/**
		Pieces es una secuencia de [Piece]. Se trata de una lista
		de estructuras de tipo [Piece].

		@see Piece
	**/
	sequence<Piece> Pieces;
	/**
		TZones es una secuencia de [TZone]. Se trata de una lista
		de estructuras de tipo [TZone].

		@see TZone
	**/
   sequence<TZone> TZones;

	/**
		Excepcion basica de Yafridng. Todas las excepciones heredan
		de YafridngException.
	**/
	exception YafridngException
	{
		/**
			Cadena que contiene la razon por la que se ha lanzado
			la excepcion.
		**/
		string reason;
	};

	/**
		Excepcion que se lanza si hay algun problema al renderizar
		una unidad de trabajo.
	**/
   exception RenderingFailedException extends YafridngException
   {
   };

	/**
		Excepcion que se lanza si hay algun problema al acceder a
		un archivo local.
	**/
   exception FileAccessException extends YafridngException
   {
   };

	/**
		Excepcion que se lanza si se intenta añadir un nodo que ya
		existia previamente.
	**/
   exception NodeAlreadyExistsException extends YafridngException
   {
   };

	/**
		Excepcion que se lanza si ya no se pueden reservar mas nodos.
		Bien porque se ha llegao al limite permitido o bien porque ya
		no hay mas nodos disponibles.
	**/
   exception NoMoreNodesException extends YafridngException
   {
   };

	/**
		La interfaz File permite la lectura de un archivo por parte
		de un cliente.
	**/
   interface File
   {
		/**
			La operacion next devuelve la siguiente secuencia esperada.

			@return Una secuencia de bytes que se corresponde con los bytes
			leidos.

			@see Ice::ByteSeq
		**/
		["ami", "amd", "cpp:array"] Ice::ByteSeq next();
   };

	/**
		La interfaz FileStore define la operacion que nos permite 
		abrir un archivo para su posterior lectura. Para abrir 
		un archivo es necesario utilizar la operacion read.
	**/
	interface FileStore
   {
		/**
			La operacion read abre un archivo en el servidor y nos
			devuelve un proxy File para su posterior lectura.

			@param name indica el nombre del archivo que se desea leer.
			@param num indica el numero de bytes que se transferiran 
			con cada llamada a la funcion [next].
			@param offset indica la posicion a partir de la cual se 
			va a leer en el archivo.
			@param pieceSize indica el numero de bytes totales que se
			van a leer.

			@throws FileAccessException si ocurre algun error a la 
			hora de abrir el archivo.

			@return Un proxy a un objeto de tipo [File].

			@see FileAccessException
			@see File
		**/
		File* read(string name, int num, int offset, int pieceSize)
		throws FileAccessException;
   };

	/**
		La interfaz P2PBroker define las operaciones proporcionadas 
		por el gestor de intercambio de archivos. Sera utilizado por
		los nodos para notificar las piezas escritas y para solicitar
		las piezas restantes.
	**/
   interface P2PBroker{
		/**
			La operación notifyPiece se utiliza por parte de los nodos
			para indicar que ha concluido con la escritura de una pieza
			de archivo en disco.

			@param piece indica el numero de la pieza que se ha escrito
			en disco.
			@param FileStore es un proxy que permite la creacion de 
			proxies de tipo [File] para la posterior lectura del
			archivo.

			@see FileStore
		**/
		void notifyPiece(int piece, FileStore* fileSt);

		/**
			La operacion getFileKeeper se utiliza para obtener una 
			porcion del archivo intercambiado. Un nodo solicita una 
			pieza y el cliente devolvera un proxy a un objeto de tipo 
			[File] mediante el cual se podra leer la pieza solicitada.
			
			@param piece indica el numero de pieza solicitada.

			@see File
		**/
		File* getPieceKeeper(int piece/*, string nodeId*/);
	};

	/**
		La interfaz YafridngRenderManager define las operaciones 
		proporcionadas por el gestor de renderizado. Su funcion
		sera la de asignar las unidades de trabajo pendientes de
		ejecucion y la recuperacion de los resultados.
	**/
	interface YafridngRenderManager
   {
		/**
			La operacion queryZone se utiliza para solicitar una
			unidad de trabajo por parte de un nodo.

			@param nodeId es el identificador del nodo que 
			realiza la peticion.
			
			@return un entero que se corresponde con la unidad de
			trabajo asignada.
		**/
		int queryZone(string nodeId);

		/**
			La operacion updateZone se utiliza para indicar la 
			consecucion de una unidad de trabajo por parte de un 
			nodo.

			@param zone indica el numero de la unidad de trabajo 
			que se ha ejecutado.
			@param fileName indica el nombre del archivo que contiene 
			el resultado.
			@param f es un proxy a un objeto de tipo [File] para la 
			recuperacion del resultado.

			@see File
		**/
		["ami", "amd"] void updateZone(int zone, string fileName, File* f);
	};

	/**
		La interfaz YafridngRenderer define las operaciones 
		proporcionadas por un nodo. El cliente las utilizara 
		para renderizar una escena.
	**/
	interface YafridngRenderer
	{
		/**
			La operacion obtainFile comienza el proceso de obtencion
			del archivo que contiene la escena. Cuando finalice su 
			ejecucion el nodo tendra el archivo completo.

			@param piecesList es una secuencia de [Piece]. Contiene 
			la informacion de todas las piezas en las que se ha 
			dividido el archivo.
			@param piece indica el numero de pieza asignada al nodo.
			@param fileSize indica el tamaño total del archivo que 
			contiene la descripcion de la escena.
			@param f es un proxy a un objeto de tipo [File] que se 
			utilizara para obtener la pieza asignada.
			@param broker es un proxy a un objeto de tipo [P2PBroker]
			que se utilizara para la localizacion de las piezas 
			restantes.

			@see Pieces
			@see File
			@see P2PBroker
		**/
		void obtainFile(Pieces piecesList, int piece, int fileSize, File* f, P2PBroker* broker);

		/**
			La operacion render comienza el proceso de renderizado de 
			la escena. El nodo ira solicitando la asignacion de unidades
			de trabajo hasta que el gestor de renderizadole indique que 
			se ha renderizado la escena completa.

			@param zones es una secuencia de [TZone]. Contiene la 
			informacion acerca de las unidades de trabajo.
			@param manager es un proxy a un objeto de tipo 
			[YafridngRenderManager]. El nodo lo utilizara para obtener nuevas
			tareas y remitir los resultados de las ya realizadas.

			@throws RenderingFailedException si ocurre algun error durante
			el renderizado.
	
			@see TZones
			@see YafridngRenderManager
		**/
		void render(TZones zones, YafridngRenderManager* manager)
		throws RenderingFailedException;

		/**
			La operacion flush libera los recursos utilizados por un renderer. 
			Se invocara cuando finalice el renderizado de la escena.
		**/
		void flush();
	};

	/**
		La interfaz YafridngRendererFactory se utilizara para crear e
		inicializar objetos del tipo [YafridngRenderer].
	**/  
	interface YafridngRendererFactory
	{
		/**
			La opearcion createRenderer crea un objeto de tipo [YafridngRenderer]
			y devuelve un proxy para su manipulacion.

			@param RenderEngine indica el motor de render utilizado. Puede
			tomar dos valores, 0 para Blender y 1 para Yafray.
			@param scene contiene el nombre de la escena que se va a 
			renderizar.

			@return Un proxy al objeto creado. El cliente utilizara
			este proxy para la manipulacion del objeto.
		**/
		YafridngRenderer* createRenderer(int RenderEngine, string scene);
	};

	/**
		La interfaz YafridngNodeManager define las operaciones 
		necesarias para la gestion de los nodos que proporcionan 
		sus ciclos de cpu.
	**/
   interface YafridngNodeManager
   {
		/**
			La operacion addNode permite la adicion de un nodo al sistema.
			
			@param factory es un proxy a un objeto de tipo [YafridngRendererFactory].
			Existira	un objeto de este tipo por cada nodo, permitiendo 
			la posterior creacion de objetos	de tipo [YafridngRenderer].

			@throws NodeAlreadyExistsException si ya existe un nodo
			con la misma identidad en el sistema.

			@see YafridngRendererFactory
			@see NodeAlreadyExistsException
		**/
		void addNode(YafridngRendererFactory* factory)
		throws NodeAlreadyExistsException;

		/**
			La operacion allocateNode permite la reserva de uno de
			los nodos para la ejecucion de un trabajo.

			@return un proxy a un objeto de tipo [YafridngRendererFactory]
			que sera utilizado para la creacion de objetos de tipo 
			[YafridngRenderer].

			@throws NoMoreNodesException si ya no hay mas recursos 
			disponibles.

			@see YafridngRendererFactory
		**/
		YafridngRendererFactory* allocateNode()
		throws NoMoreNodesException;

		/**
			La operacion releaseNode permite la liberacion de un recurso
			previamente reservado.
			
			@param factory indica el recurso que se ha de liberar.
		**/
		void releaseNode(YafridngRendererFactory* factory);
   };

	/**
		La interfaz RenderSession define las operaciones que se 
		pueden ejecutar a traves de una sesion. Es necesario 
		establecer una sesion para hacer uso de Yafrid-NG. La 
		sesion hara de intermediario entre los usuarios de Yafrid-NG 
		y el sistema.

		@see Glacier2::Session
	**/
	interface RenderSession extends Glacier2::Session
   {
		/**
			La operacion keepAlive se invocara de forma periodica 
			para mantener la sesion activa y no destruirla prematuramente.
		**/
		void keepAlive();

		/**
			La funcion create se invocara, por parte del cliente,
			para obtener un recurso computacional.
			
			@param renderEngine indica el motor de render que se 
			va a utilizar.
			@param scene indica el nombre de la escena que se va 
			a generar.

			@return un proxy a un objeto de tipo [YafridngRenderer] 
			que sera utilizado para la ejecucion de un trabajo.

			@throws NoMoreNodesException si el cliente ya ha reservado
			los recursos maximos permitidos.

			@see YafridngRenderer
			@see NoMoreNodesException
		**/
		YafridngRenderer* create(int renderEngine, string scene)
		throws NoMoreNodesException;

		/**
			La operacion addNode permite la agregacion de un nuevo 
			recurso computacional a Yafrid-NG.

			@param node indica la factoria proporcionada por el nodo
			para la creacion de objetos de tipo	[YafridngRenderer].

			@see YafridngRendererFactory
		**/
		void addNode(YafridngRendererFactory* node);
   };
};
